<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件委托</title>
    <link rel="stylesheet" href="src/assets/reset.min.css">
    <style>
        html,
        body {
            height: 100%;
            overflow: hidden;
        }

        .center {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }

        #root {
            width: 300px;
            height: 300px;
            background: lightblue;
        }

        #outer {
            width: 200px;
            height: 200px;
            background: lightgreen;
        }

        #inner {
            width: 100px;
            height: 100px;
            background: lightcoral;
        }
    </style>
</head>

<body>
    <div id="root" class="center">
        <div id="outer" class="center">
            <div id="inner" class="center"></div>
        </div>
    </div>

    <!-- IMPORT JS -->
    <script>
        const html = document.documentElement,
            body = document.body,
            root = document.querySelector('#root'),
            outer = document.querySelector('#outer'),
            inner = document.querySelector('#inner')

        /* React18合成事件原理 */
        const handlerSyntheticEv = function handlerSyntheticEv(ev) {
            // 把原生的事件对象进行处理，让其变为合成事件对象「目的：让各个浏览器统一」
            // ...
            return ev
        }
        root.addEventListener('click', function (ev) {
            // 获取传播路径「从内到外」
            let path = ev.composedPath()
            // 获取合成事件对象
            let syntheticBaseEvent = handlerSyntheticEv(ev)
            path.reverse().forEach(elem => {
                if (!elem.hasOwnProperty('onClickCapture')) return
                elem.onClickCapture(syntheticBaseEvent)
            })
        }, true)
        root.addEventListener('click', function (ev) {
            let path = ev.composedPath()
            let syntheticBaseEvent = handlerSyntheticEv(ev)
            path.forEach(elem => {
                if (!elem.hasOwnProperty('onClick')) return
                elem.onClick(syntheticBaseEvent)
            })
        }, false)

        /* JSX渲染 */
        outer.onClickCapture = function () { console.log('outer 捕获「合成」') }
        outer.onClick = function () { console.log('outer 冒泡「合成」') }
        inner.onClickCapture = function () { console.log('inner 捕获「合成」') }
        inner.onClick = function () { console.log('inner 冒泡「合成」') }

        /* 手动做的事件绑定 */
        window.addEventListener('click', function () { console.log('window 捕获') }, true)
        window.addEventListener('click', function () { console.log('window 冒泡') }, false)

        document.addEventListener('click', function () { console.log('document 捕获') }, true)
        document.addEventListener('click', function () { console.log('document 冒泡') }, false)

        html.addEventListener('click', function () { console.log('html 捕获') }, true)
        html.addEventListener('click', function () { console.log('html 冒泡') }, false)

        body.addEventListener('click', function () { console.log('body 捕获') }, true)
        body.addEventListener('click', function () { console.log('body 冒泡') }, false)

        root.addEventListener('click', function () { console.log('root 捕获') }, true)
        root.addEventListener('click', function () { console.log('root 冒泡') }, false)

        outer.addEventListener('click', function () { console.log('outer 捕获') }, true)
        outer.addEventListener('click', function () { console.log('outer 冒泡') }, false)

        inner.addEventListener('click', function () { console.log('inner 捕获') }, true)
        inner.addEventListener('click', function () { console.log('inner 冒泡') }, false)
    </script>
</body>

</html>